﻿/*
ParallelPlatform Project - A web platform to distribute and share knowledge
Online Editor - An online tool to create and play animations
Copyright (C) 2011 Daniel Guerrero Martínez & Sergio Rodríguez Lumley

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package Classes{
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.filters.DropShadowFilter;
	import flash.filters.BitmapFilterQuality;
	
	/**
	  Controller of Play and Pause of Scenes
	*/
	public class PlayerController extends MovieClip {
		
		public const PLAY:uint 	= 0;
		public const PAUSE:uint = 1;
		
		private const RADIUS:Number = 20;
		private const BORDER_RADIUS:Number = 22;
		
		private var fps:uint; // Frames per second of the animation (25 by default)
		private var defaultWtime:Number; // Time player will wait by defualt (in Seconds)
		private var currentTick:uint;
		private var maxTicks:uint;
		private var playFunc:Function; // Function to call when countdown ends
		private var status:uint; // Paused or Playing
		private var isCounting:Boolean;
		
		/**
		  Constructor
		  @param playFunction Function to call when countdown finishes
		*/
		public function PlayerController(playFunction:Function){
			fps 			= 25;
			defaultWtime 	= 20; // 20seconds
			status 			= PLAY;
			playFunc 		= playFunction;
			maxTicks		= 100;
			currentTick		= 0;
			isCounting		= false;
			buttonMode		= true;
			useHandCursor	= true;
			
			this.filters	= new Array(new DropShadowFilter(
								5, 		// Distance
								90, 	// Angle
								0x000000, // Color
								0.5, 	// Alpha
								25, 	// Blur X
								25, 	// Blur Y
								1, 		// Strength
								BitmapFilterQuality.LOW)
						 );
			
			// Draw background
			redraw();
		}
		
		/**
		  Sets the playFunction
		  @param playFunction Function to call when countdown finishes
		*/
		public function setPlayFunction(playFunction:Function):void{
			playFunc = playFunction;
		}
		
		/**
		  Sets the status of the player (PLAY, PAUSE)
		  @param stat uint that indicates the new status to be set
		*/
		public function setStatus(stat:uint):void{
			status = stat;
			redraw();
		}
		
		/**
		  Swaps the current status of the controller, if it was in Pause,
		  now it will be in play, and viceversa. If the counter has expired
		  and it is swaped to play, controller will call the end function
		*/
		public function swapStatus():void{
			status = (status+1)%2;
			redraw();
			if(status == PLAY && currentTick >= maxTicks) playFunc(); // Call to play function
		}
		
		/**
		  Gets the status of the controller
		  @return uint with the status
		*/
		public function getStatus():uint{
			return status;
		}
		
		/**
		  Restarts the player's timer to make it appear full
		*/
		public function restart():void{
			maxTicks		= 150;
			currentTick		= 0;
			if(isCounting){
				this.removeEventListener(Event.ENTER_FRAME, periodicTick);
				isCounting = false;
			}
			redraw();
		}
		
		/**
		  Begins playing the controller ticks
		  @param seconds Number with the number of seconds to countdown (Optional)
		*/
		public function begin(seconds:Number=0):void{
			var nsecs:Number = defaultWtime;
			if(seconds != 0) nsecs = seconds;
			
			maxTicks = nsecs*fps;
			currentTick = 0;
			//trace(String(maxTicks)+" "+ String(fps));
			
			if(! isCounting)
				this.addEventListener(Event.ENTER_FRAME, periodicTick);
			isCounting = true;
			//this.addEventListener(MouseEvent.CLICK, tickHack);
		}
		
		/**
		  Ends the countdown and calls the play function if status is in PLAY
		*/
		public function end():void{
			this.removeEventListener(Event.ENTER_FRAME, periodicTick);
			if(status == PLAY) playFunc(); // Call to play function
		}
		
		/**
		  Stops the controller from counting
		*/
		public function stopCount():void{
			if(isCounting)
				this.removeEventListener(Event.ENTER_FRAME, periodicTick);
			isCounting = false;
		}
		
		//********** PRIVATE FUNCTIONS ************//
		/**
		  Periodic event to repaint the counter, we assume (0, 0) is the CENTER of the counter
		*/
		private function periodicTick(evt:Event):void{
			if(currentTick >= maxTicks) this.end();
			redraw();
			currentTick = Math.min(currentTick+1, maxTicks);
		}
		
		/**
		  Draws the controller
		*/
		private function redraw():void{
			this.graphics.clear();
			drawBackground();
			drawSymbol();
			drawTimer();
		}
		
		
		/**
		  Draws the background of the controller
		*/
		private function drawBackground():void{
			graphics.beginFill(0x999999);
			graphics.drawCircle(0, 0, BORDER_RADIUS+4);
			graphics.endFill();
			
			graphics.beginFill(0x333333);
			graphics.drawCircle(0, 0, RADIUS);
			graphics.endFill();
			
		}
		
		/**
		  Draws the symbol of Play or Pause of the controller
		*/
		private function drawSymbol():void{
			graphics.beginFill(0x999999);
			if(status == PLAY){
				graphics.moveTo(-RADIUS/2+3, -RADIUS/2);
				graphics.lineTo(-RADIUS/2+3,  RADIUS/2);
				graphics.lineTo( RADIUS/2+3,  0);
			}else{
				graphics.drawRect(-(RADIUS/2 - RADIUS/6)-3, -RADIUS/2,
								  RADIUS/3, RADIUS);
				graphics.drawRect(  RADIUS/2 - RADIUS/6 -3, -RADIUS/2,
								  RADIUS/3, RADIUS);
			}
			graphics.endFill();
		}
		
		/**
		  Draws the timer of the controller
		*/
		private function drawTimer():void{
			graphics.lineStyle(4,0x333333, 1, false, "normal", "square", "round");
			this.graphics.moveTo(0, -BORDER_RADIUS);
			
			var t:Number;
			for(var i:uint = maxTicks; i> currentTick; --i){
				t = i*360/maxTicks;
				// x = center_x + radius*cos(t)
				// y = center_y + radius*sin(t)
				this.graphics.lineTo(
							BORDER_RADIUS*Math.cos(t*Math.PI/180 - Math.PI/2),
							BORDER_RADIUS*Math.sin(t*Math.PI/180 - Math.PI/2));
			}
		}
		
	}
}